/*
 * Copyright 2012-2014 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package com.jqd.framework.core.hessian.biz.action;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.OrderComparator;

import com.jqd.framework.core.exception.BusinessServiceException;
import com.jqd.framework.core.exception.WebControllerException;
import com.jqd.framework.core.hessian.biz.action.support.ActionHandlerExecution;
import com.jqd.framework.core.hessian.model.ServiceRequest;
import com.jqd.framework.core.hessian.model.ServiceResponse;
import com.jqd.framework.core.hessian.web.controller.ApplicationControllerHandler;
import com.jqd.framework.util.Assert;
import com.jqd.framework.util.PropertiesUtils;

/**
 * 
 * <p>
 * Description: 该类相当于从controller到action调用的一个全局网关， 所有从controller到action层的请求都将被该类捕获，该类捕获到请求
 * 之后，会将这些请求分发给某个具体的action对象（通过{@code ActionHandlerMapping}接口）， 然后通过调用该action对象中的相应的方法（通过
 * {@code ActionHandlerAdapter}接口）完成请求调用。</br> 对于映射请求接口{@code ActionHandlerMapping}及方法调用
 * {@code ActionHandlerAdapter}
 * 的实现该类提供了一些默认配置，详见：ApplicationControllerHandler.properties，所有的默认配置都可以被用户
 * 配置所覆盖，当用户没有显示的提供配置时，默认配置将发挥作用。
 * </p>
 * 
 * @author liaozhicheng.cn@gmail.com
 * @date 2012-6-11
 * @since 1.0
 * @see com.jqd.framework.core.hessian.biz.action.ActionHandlerMapping
 * @see com.jqd.framework.core.hessian.biz.action.ActionHandlerAdapter
 */
public class ApplicationControllerHandlerSupport implements ApplicationControllerHandler,
		ApplicationContextAware {
	
	private static final String DEFAULT_STRATEGIES_PATH = "com/jqd/framework/core/hessian/ApplicationControllerHandler.properties";
	
	private static final Properties DEFAULT_STRATEGIES;
	
	static {
		// 通过配置文件载入默认配置
		// 所有的这些默认配置可以被开发者通过配置文件覆盖
		// 只有在没有找到用户配置时才使用默认配置
		
		try {
			DEFAULT_STRATEGIES = PropertiesUtils.loadProperties(DEFAULT_STRATEGIES_PATH);
		}
		catch (IOException e) {
			throw new IllegalStateException(
					"Could not load 'ApplicationControllerHandler.properties': " + e.getMessage());
		}
	}
	
	// 请求映射接口集合
	private List<ActionHandlerMapping> actionHandlerMappings;
	
	// action方法适配器集合
	private List<ActionHandlerAdapter> actionHandlerAdapters;
	
	
	// --------------------------------------------
	// implements ApplicationControllerHandler
	// --------------------------------------------
	
	public ServiceResponse handleRequest(ServiceRequest serviceRequest)
			throws BusinessServiceException {
		
		Assert.notNull(serviceRequest, "Parameter 'serviceRequest' can not be null");
		
		ServiceResponse serviceResponse = null;
		try {
			ActionHandlerExecution handlerExecution = getActionHandlerExecution(serviceRequest);
			
			// 正在的处理controller请求的action实例
			Object actionHandler = handlerExecution.getHandler();
			
			ActionHandlerAdapter handlerAdapter = getActionHandlerAdapter(serviceRequest,
					actionHandler);
			
			// 获取拦截器，并调用用户配置的拦截器的 #preHandle 方法进行预处理，一种AOP的实现
			ActionHandlerInterceptor[] interceptors = handlerExecution.getInterceptors();
			if (interceptors != null && interceptors.length > 0) {
				for (ActionHandlerInterceptor interceptor : interceptors) {
					interceptor.preHandle(serviceRequest, actionHandler);
				}
			}
			
			serviceResponse = handlerAdapter.handle(serviceRequest, handlerExecution.getHandler());
			
			// 调用配置的拦截器的 #postHandle 方法进行后处理，从最后面的拦截器开始执行
			if (interceptors != null && interceptors.length > 0) {
				for (int i = interceptors.length; i > 0; i--) {
					interceptors[i].postHandle(serviceRequest, serviceResponse, actionHandler);
				}
			}
		}
		catch (Exception ex) {
			throw new BusinessServiceException(ex);
		}
		
		return serviceResponse;
	}
	
	
	// -------------------------------------------------
	// implements ApplicationContextAware
	// -------------------------------------------------
	
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		
		initActionHandlerMapping(applicationContext);
		initActionHandlerAdapter(applicationContext);
	}
	
	
	// /// private methods
	
	private void initActionHandlerMapping(ApplicationContext context) {
		this.actionHandlerMappings = null;
		
		// 找到用户的默认配置，如果用户没配置则使用默认配置
		Map<String, ActionHandlerMapping> matchBeans = context.getBeansOfType(
				ActionHandlerMapping.class, false, false);
		if (!matchBeans.isEmpty()) {
			this.actionHandlerMappings = new ArrayList<ActionHandlerMapping>(matchBeans.values());
			OrderComparator.sort(this.actionHandlerMappings);
		}
		
		if (this.actionHandlerMappings == null) {
			this.actionHandlerMappings = getDefaultStrategies(context, ActionHandlerMapping.class);
		}
		
	}
	
	
	private void initActionHandlerAdapter(ApplicationContext context) {
		this.actionHandlerAdapters = null;
		
		Map<String, ActionHandlerAdapter> matchBeans = context.getBeansOfType(
				ActionHandlerAdapter.class, false, false);
		if (!matchBeans.isEmpty()) {
			this.actionHandlerAdapters = new ArrayList<ActionHandlerAdapter>(matchBeans.values());
			OrderComparator.sort(this.actionHandlerAdapters);
		}
		
		// add default configuration
		if (this.actionHandlerAdapters == null) {
			this.actionHandlerAdapters = getDefaultStrategies(context, ActionHandlerAdapter.class);
		}
	}
	
	
	@SuppressWarnings("unchecked")
	private <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategicInterface) {
		
		List<T> result = new ArrayList<T>();
		
		String key = strategicInterface.getName();
		String values = DEFAULT_STRATEGIES.getProperty(key);
		
		if (StringUtils.isNotEmpty(values)) {
			String[] classNames = values.trim().split(",");
			for (String className : classNames) {
				try {
					// 不能直接通过反射的#newInstance()方法产生对象
					// 因为这些类有些初始化的方法需要在容器初始化该对象之后执行
					Class<?> clazz = Class.forName(className);
					Object target = context.getAutowireCapableBeanFactory().createBean(clazz);
					result.add((T) target);
				}
				catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}
	
	
	private ActionHandlerExecution getActionHandlerExecution(ServiceRequest serviceRequest)
			throws WebControllerException {
		
		for (ActionHandlerMapping handlerMapping : this.actionHandlerMappings) {
			ActionHandlerExecution handler = handlerMapping.getHandler(serviceRequest);
			if (handler != null)
				return handler;
		}
		
		throw new WebControllerException("No handler found");
	}
	
	
	private ActionHandlerAdapter getActionHandlerAdapter(ServiceRequest serviceRequest,
			Object handler) throws WebControllerException {
		
		for (ActionHandlerAdapter adapter : this.actionHandlerAdapters) {
			if (adapter.supports(serviceRequest, handler))
				return adapter;
		}
		
		throw new WebControllerException("No handler adapter found");
	}
	
}
